<h2>Why is this an issue?</h2>
<p>Both the <code>Enumerable.First</code> extension method and the <code>LinkedList&lt;T&gt;.First</code> property can be used to find the first value
in a <code>LinkedList&lt;T&gt;</code>. However, <code>LinkedList&lt;T&gt;.First</code> is much faster than <code>Enumerable.First</code>. For small
collections, the performance difference may be minor, but for large collections, it can be noticeable. The same applies for the <code>Last</code>
property as well.</p>
<p><strong>Applies to:</strong></p>
<ul>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1.first">LinkedList&lt;T&gt;.First</a> </li>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1.last">LinkedList&lt;T&gt;.Last</a> </li>
</ul>
<h3>What is the potential impact?</h3>
<p>We measured a significant improvement both in execution time and memory allocation. For more details see the <code>Benchmarks</code> section from
the <code>More info</code> tab.</p>
<h2>How to fix it</h2>
<p>The <code>First</code> and <code>Last</code> properties are defined on the <code>LinkedList</code> class, and the extension method call can be
replaced by calling the propery instead.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
int GetFirst(LinkedList&lt;int&gt; data) =&gt;
    data.First();
</pre>
<pre data-diff-id="2" data-diff-type="noncompliant">
int GetLast(LinkedList&lt;int&gt; data) =&gt;
    data.Last();
</pre>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
int GetFirst(LinkedList&lt;int&gt; data) =&gt;
    data.First.Value;
</pre>
<pre data-diff-id="2" data-diff-type="compliant">
int GetLast(LinkedList&lt;int&gt; data) =&gt;
    data.Last.Value;
</pre>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
  <li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1">LinkedList&lt;T&gt;</a> </li>
</ul>
<h3>Benchmarks</h3>
<table>
  <colgroup>
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
  </colgroup>
  <thead>
    <tr>
      <th>Method</th>
      <th>Runtime</th>
      <th>Mean</th>
      <th>Standard Deviation</th>
      <th>Allocated</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><p>LastMethod</p></td>
      <td><p>.NET 7.0</p></td>
      <td><p>919,577,629.0 ns</p></td>
      <td><p>44,299,688.61 ns</p></td>
      <td><p>48504 B</p></td>
    </tr>
    <tr>
      <td><p>LastProperty</p></td>
      <td><p>.NET 7.0</p></td>
      <td><p>271.8 ns</p></td>
      <td><p>15.63 ns</p></td>
      <td><p>-</p></td>
    </tr>
    <tr>
      <td><p>LastMethod</p></td>
      <td><p>.NET Framework 4.6.2</p></td>
      <td><p>810,316,427.1 ns</p></td>
      <td><p>47,768,482.31 ns</p></td>
      <td><p>57344 B</p></td>
    </tr>
    <tr>
      <td><p>LastProperty</p></td>
      <td><p>.NET Framework 4.6.2</p></td>
      <td><p>372.0 ns</p></td>
      <td><p>13.38 ns</p></td>
      <td><p>-</p></td>
    </tr>
  </tbody>
</table>
<h4>Glossary</h4>
<ul>
  <li> <a href="https://en.wikipedia.org/wiki/Arithmetic_mean">Mean</a> </li>
  <li> <a href="https://en.wikipedia.org/wiki/Standard_deviation">Standard Deviation</a> </li>
  <li> <a href="https://en.wikipedia.org/wiki/Memory_management">Allocated</a> </li>
</ul>
<p>The results were generated by running the following snippet with <a href="https://github.com/dotnet/BenchmarkDotNet">BenchmarkDotNet</a>:</p>
<pre>
private LinkedList&lt;int&gt; data;
private Random random = new Random();

[Params(100_000)]
public int Size { get; set; }

[Params(1_000)]
public int Runs { get; set; }

[GlobalSetup]
public void Setup() =&gt;
    data = new LinkedList&lt;int&gt;(Enumerable.Range(0, Size).Select(x =&gt; random.Next()));

[Benchmark(Baseline = true)]
public void LastMethod()
{
    for (var i = 0; i &lt; Runs; i++)
    {
        _ = data.Last();                // Enumerable.Last()
    }
}

[Benchmark]
public void LastProperty()
{
    for (var i = 0; i &lt; Runs; i++)
    {
        _ = data.Last;                  // Last property
    }
}
</pre>
<p>Hardware configuration:</p>
<pre>
BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
11th Gen Intel Core i7-11850H 2.50GHz, 1 CPU, 16 logical and 8 physical cores
  [Host]               : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
  .NET 7.0             : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
  .NET Framework 4.6.2 : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
</pre>

